/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package domain;

import gui2.outputInterface;

/**
 *
 * @author Hjortzzor.. fast nää markus har ju gjort de mesta :)
 */
public class MinMax {
    GameGrid grid;
    int playerId;
    int depthLevel;
    //private static outputInterface out;
    private outputInterface outInterface;
    int count = 0;

    
    public MinMax(GameGrid grid, int playerId, int level, outputInterface outInterface){
        this.grid = copyGrid(grid);
        this.playerId = playerId;
        this.depthLevel=level;
        this.outInterface = outInterface;
        
        switch(level){
            case 1:
                this.depthLevel=2;
                break;
            case 2:
                this.depthLevel=4;
                break;
            case 3:
                this.depthLevel=6;
                break;
            default:
                this.depthLevel=1;
                break;
        }
        //System.out.println("player"+playerId+" is level "+level+"and searches on depth "+this.depthLevel);
        
        
    }
    private int oponentOf(int playerId){
        if(playerId == 1){
            return 2;
        }
        return 1;
    }
    private GameGrid copyGrid(GameGrid gridOne){
        GameGrid gridCopy = new GameGrid();
        for(int y = 0; y<8; y++){
            for(int x = 0; x<8; x++){
                if(gridOne.GameGrid[x][y].getOwner()==1){
                    gridCopy.GameGrid[x][y].setOwner(1);
                }
                else if(gridOne.GameGrid[x][y].getOwner()==2){
                    gridCopy.GameGrid[x][y].setOwner(2);
                }else{
                    gridCopy.GameGrid[x][y].setOwner(0);
                }
                
            }
               
        }
        return gridCopy;
    }
    public Move findBestMove(){
        GameGrid tempGrid = copyGrid(grid);
        
        int max = -999999999;
        int value;
        Move currentBest = new Move(0,0);
        
        for(int x = 0; x < 8; x++){
            for(int y = 0; y < 8; y++){
                if(grid.isLegalMove(playerId, x, y)){
                   count++;
                   tempGrid.makeMove(playerId, x, y);
                   value = minValue(tempGrid, depthLevel, x, y);
                   
                    if(value > max){
                        max = value;
                        currentBest.setX(x);
                        currentBest.setY(y);
                    }
                    else{
                        //System.out.println("nope " + value +"<"+max);
                    }
                
                }
                
            }
        }
        //System.out.println("trying "+playerId + " with "+max +" on "+currentBest.getX()+" "+currentBest.getY());
        
        //grid.printGrid();
        outInterface.printToOutput("----MINMAX SEARCH----");
        outInterface.printToOutput("PLAYER: "+playerId+" DEPTH:"+depthLevel);
        outInterface.printToOutput("SEARCHES:"+count);
        outInterface.printToOutput("");
        return currentBest;
    }
    private int maxValue(GameGrid grid, int depth, int newX, int newY){
        //System.out.println("there "+ depth);
        int v = -999999998;
        GameGrid tempGrid = new GameGrid();
        
        //returnera utility om terminal state
        if(grid.isTerminalState()){
            //System.out.println("terminal max, found terminal state");
            return grid.getValueUtility(playerId, newX, newY);
        }
        //returnera utility om vi nått sökdjupet
        if(depth == 0){
            //System.out.println("terminal max found depth");
           return grid.getValueUtility(playerId, newX, newY);
        }
        
        depth--;
        
        for(int y=0; y<8; y++){
            for(int x=0; x<8; x++){
                if(grid.isLegalMove(playerId, x, y)){
                    count++;
                    //kopiera grid
                    tempGrid = copyGrid(grid);
                    tempGrid.makeMove(playerId, x, y);
                    //som i boken.
                    v = max(v, minValue(tempGrid, depth, x, y));
                }
            }
        }
        
        //System.out.println("not terminal min");
        return v;
    }
    
    private int minValue(GameGrid grid, int depth, int newX, int newY){
        //System.out.println("here "+ depth);
        int v = 999999999;
        GameGrid tempGrid = new GameGrid();

        //returnera utility om terminal state
        if(grid.isTerminalState()){
            return grid.getValueUtility(oponentOf(playerId), newX, newY);
        }
        //returnera utility om vi nått sökdjupet
        if(depth <= 0){
            return grid.getValueUtility(oponentOf(playerId), newX, newY);
        }
        
        depth--;
        
        for(int y=0; y<8; y++){
            for(int x=0; x<8; x++){
                if(grid.isLegalMove(oponentOf(playerId), x, y)){
                    count++;
                    //kopiera grid
                    tempGrid = copyGrid(grid);
                    tempGrid.makeMove(oponentOf(playerId), x, y);
                    //som i boken.
                    v = min(v, maxValue(tempGrid, depth, x, y));
                }
            }
        }
        //System.out.println("not terminal min");
        return v;
    }
    
    
    private int max(int a, int b){
        if(a>=b){
            return a;
        }
        return b;    
    }
    private int min(int a, int b){
        if(a<b){
            return a;
        }
        return b;    
    }
     
}
